package com.xiaoyu.izf.service;


import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.google.common.collect.Lists;
import com.xiaoyu.izf.aspect.FieldSetNotify;
import com.xiaoyu.izf.config.SysConfig;
import com.xiaoyu.izf.model.CommissionGetLog;
import com.xiaoyu.izf.model.UserInfo;
import com.xiaoyu.izf.model.page.DataTableBean;
import com.xiaoyu.izf.model.page.ParamListBean;
import com.xiaoyu.izf.repository.UserInfoDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.sql.Timestamp;
import java.util.List;


@Service
public class UserInfoService extends BaseService{

	@Autowired
	private UserInfoDao userInfoDao;
	@Autowired
	private JdbcTemplate jdbcTemplate;

//	@FieldSetNotify
	public UserInfo adminUserOne(int id) {
		return userInfoDao.findById(id);
	}
	
	public UserInfo adminUserByUserName(String userName) {
		return userInfoDao.findByUserName(userName);
	}

	public UserInfo adminUserByOfficialServiceNumber(String officialServiceNumber) {
		return userInfoDao.findByOfficialServiceNumber(officialServiceNumber);
	}

	public void adminUserSave(UserInfo user) {
		userInfoDao.save(user);
	}

	public UserInfo save(UserInfo user) {
		return userInfoDao.save(user);
	}

	public void commissionPay(CommissionGetLog getLog){

	}

	public DataTableBean list(ParamListBean param,UserInfo user) {
		PageRequest pageRequest = buildPageRequestSort(param.getPageNo(), param.getPageLength(), "id",param.getFieldName(),param.getCompositorType());

		//添加查询条件
		Page<UserInfo> page = userInfoDao.findAll(new Specification<UserInfo>() {

			/**
			 * 构建查询条件（Predicate断言对象）
			 * @param root entity：UserInfo
			 * @param query
			 * @param cb 条件构建器
			 * @return
			 */
			@Override
			public Predicate toPredicate(Root<UserInfo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				//断言列表，可以添加多个断言
				List<Predicate> predicates = Lists.newArrayList();
				//准备结合断言链
				predicates.add(cb.conjunction());

				if (StringUtils.hasLength(param.getParam().get("uid"))){
					//使用CriteriaBuilder条件构建器构建断言，并加入断言列表
					predicates.add(
							//断言为equals(期待值，实际值)，跟junit的断言类似
							cb.equal(root.get("id").as(Integer.class),param.getParam().get("uid")));
				}

				//断言1：vip等级
				if (StringUtils.hasLength(param.getParam().get("vipType"))){
					//使用CriteriaBuilder条件构建器构建断言，并加入断言列表
					predicates.add(
							//断言为equals(期待值，实际值)，跟junit的断言类似
							cb.equal(root.get("vipType").as(Integer.class),param.getParam().get("vipType")));
				}

				if (StringUtils.hasLength(param.getParam().get("userName"))){
					//使用CriteriaBuilder条件构建器构建断言，并加入断言列表
					predicates.add(
							//断言为equals(期待值，实际值)，跟junit的断言类似
							cb.equal(root.get("userName").as(String.class),param.getParam().get("userName")));
				}

				if (StringUtils.hasLength(param.getParam().get("nickName"))){
					predicates.add(
							cb.like(root.get("nickName").as(String.class),"%"+param.getParam().get("nickName")+"%"));
				}

				if (StringUtils.hasLength(param.getParam().get("officialNumber"))){
					//使用CriteriaBuilder条件构建器构建断言，并加入断言列表
					predicates.add(
							//断言为equals(期待值，实际值)，跟junit的断言类似
							cb.equal(root.get("officialServiceNumber").as(String.class),param.getParam().get("officialNumber")));
				}

				String hierarchy = param.getParam().get("hierarchy");
				if (StringUtils.hasLength(hierarchy)){
					if ("1".equals(hierarchy)){
						//使用CriteriaBuilder条件构建器构建断言，并加入断言列表
						predicates.add(
								//断言为equals(期待值，实际值)，跟junit的断言类似
								cb.equal(root.get("pushUid").as(Integer.class),user.getId()));
					}else if ("2".equals(hierarchy)){
						//使用CriteriaBuilder条件构建器构建断言，并加入断言列表
						predicates.add(
								//断言为equals(期待值，实际值)，跟junit的断言类似
								cb.equal(root.get("gradePushUid").as(Integer.class),user.getId()));
					}
				}

				//断言列表加入断言，返回Predicate断言对象，交给jpa执行查询
				return cb.and(predicates.toArray(new Predicate[predicates.size()]));
			}
		},pageRequest);

//		//无查询条件
//		Page<UserInfo> page = userInfoDao.findAll(pageRequest);

		return dataTableBean(page,param);
	}
	public DataTableBean secondList(ParamListBean param) {
		PageRequest pageRequest = buildPageRequestSort(param.getPageNo(), param.getPageLength(), "id",param.getFieldName(),param.getCompositorType());

		//添加查询条件
		Page<UserInfo> page = userInfoDao.findAll(new Specification<UserInfo>() {

			/**
			 * 构建查询条件（Predicate断言对象）
			 * @param root entity：UserInfo
			 * @param query
			 * @param cb 条件构建器
			 * @return
			 */
			@Override
			public Predicate toPredicate(Root<UserInfo> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				//断言列表，可以添加多个断言
				List<Predicate> predicates = Lists.newArrayList();
				//准备结合断言链
				predicates.add(cb.conjunction());

				//断言1：vip等级
				if (StringUtils.hasLength(param.getParam().get("vipType"))){
					//使用CriteriaBuilder条件构建器构建断言，并加入断言列表
					predicates.add(
							//断言为equals(期待值，实际值)，跟junit的断言类似
							cb.equal(root.get("vipType").as(Integer.class),param.getParam().get("vipType")));
				}

				if (StringUtils.hasLength(param.getParam().get("id"))){
					//使用CriteriaBuilder条件构建器构建断言，并加入断言列表
					predicates.add(
							//断言为equals(期待值，实际值)，跟junit的断言类似
							cb.equal(root.get("id").as(Integer.class),param.getParam().get("id")));
				}

				if (StringUtils.hasLength(param.getParam().get("officialNumber"))){
					//使用CriteriaBuilder条件构建器构建断言，并加入断言列表
					predicates.add(
							//断言为equals(期待值，实际值)，跟junit的断言类似
							cb.equal(root.get("officialServiceNumber").as(String.class),param.getParam().get("officialNumber")));
				}

				//上级用户id
				predicates.add(
						//断言为equals(期待值，实际值)，跟junit的断言类似
						cb.equal(root.get("pushUid").as(Integer.class),param.getParam().get("upUserId")));

				//断言列表加入断言，返回Predicate断言对象，交给jpa执行查询
				return cb.and(predicates.toArray(new Predicate[predicates.size()]));
			}
		},pageRequest);

//		//无查询条件
//		Page<UserInfo> page = userInfoDao.findAll(pageRequest);

		return dataTableBean(page,param);
	}

	public boolean canUpVip(UserInfo userInfo,int targetVip){
		if (targetVip==21&&(userInfo.getVipType()==0||userInfo.getVipType()==1||userInfo.getVipType()==2||userInfo.getVipType()==3||userInfo.getVipType()==23)){
			return true;
		}else if (targetVip==23&&(userInfo.getVipType()==0||userInfo.getVipType()==1||userInfo.getVipType()==2||userInfo.getVipType()==3)){
			return true;
		}else if (targetVip==3&&(userInfo.getVipType()==0)){
			return true;
		}else if (targetVip==2&&(userInfo.getVipType()==0||userInfo.getVipType()==3)){
			return true;
		}else if (targetVip==1&&(userInfo.getVipType()==0||userInfo.getVipType()==2||userInfo.getVipType()==3)){
			return true;
		}
		return false;
	}

	@Transactional
	public String genNewOfficalServiceNo(UserInfo user,int vipType){
		//CAZFD201909006;
		return null;
	}


	@Transactional
	public UserInfo add(String officialServiceNumber,String userName,String nickName,int vipType,UserInfo pusher,String regionCode){
		String token = IdUtil.simpleUUID();
		UserInfo user = new UserInfo();
		user.setSource(1);
		user.setOfficialServiceNumber(officialServiceNumber);
		user.setUserName(userName);
		user.setPwd(SecureUtil.md5("123456"+ SysConfig.pwdEx));
		user.setHeadImgUrl("pic/head.png");
		user.setNickName(nickName);
		user.setToken(token);
		user.setPushCode(pushCodeGet());
		user.setToTheAccount(0);
		user.setRegionCode(regionCode);
		if(pusher==null){
			user.setPushUid(0);
			user.setGradePushUid(0);
		}else{
			user.setPushUid(pusher.getId());
			user.setGradePushUid(pusher.getPushUid());
		}
		user.setVipType(vipType);
		user.setCommission(0);
		user.setCommissionDeposit(0);
		user.setCommissionPaid(0);
		user.setCommissionPaying(0);
		user.setRegTime(new Timestamp(System.currentTimeMillis()));
		user.setLastLoginTime(new Timestamp(System.currentTimeMillis()));
		user.setIsDel(0);
		user.setIsAdmin(0);
		if (StrUtil.isBlank(officialServiceNumber)){
			if(vipType>0){
				int n = regUserCount(DateUtil.format(user.getRegTime(),"yyyy-MM"))+1;
				while (true) {
					String osn = DateUtil.format(DateUtil.date(), "yyyyMM") + NumberUtil.decimalFormat("000", n);
					UserInfo userInfo1 = userInfoDao.findByOfficialServiceNumber(osn);
					if(userInfo1==null) {
						user.setOfficialServiceNumber(osn);
						break;
					}
					n++;
				}
			}else{
				user.setOfficialServiceNumber("粉丝");
			}
		}else if (officialServiceNumber.contains("CAZF")){
			user.setOfficialServiceNumber(officialServiceNumber.substring(5));
		}else {
			user.setOfficialServiceNumber(officialServiceNumber);
		}
		user.setIsTest(0);
		user = userInfoDao.save(user);
		return user;
	}

	public void userVipUpdateByUser(UserInfo user){
		if(user.getVipType()>0){
			if(StringUtils.isEmpty(user.getOfficialServiceNumber())||"粉丝".equals(user.getOfficialServiceNumber())){
				int n = regUserCount(DateUtil.format(user.getRegTime(),"yyyy-MM"))+1;
				while (true) {
					String osn = DateUtil.format(DateUtil.date(), "yyyyMM") + NumberUtil.decimalFormat("000", n);
					UserInfo userInfo1 = userInfoDao.findByOfficialServiceNumber(osn);
					if(userInfo1==null) {
						user.setOfficialServiceNumber(osn);
						break;
					}
					n++;
				}
			}
		}
		save(user);
	}

	public int regUserCount(String date){
		Integer n = jdbcTemplate.queryForObject("select count(*) from user_info where DATE_FORMAT(reg_time,'%Y-%m')='"+date+"' and vip_type>0",Integer.class);
		return n;
	}

	public String pushCodeGet(){
		String pushCode = "";
		UserInfo userInfo = null;
		while (true){
			pushCode = RandomUtil.randomNumbers(7);
			userInfo = userInfoDao.findByPushCode(pushCode);
			if(userInfo==null){
				break;
			}
		}
		return pushCode;
	}
}
